package com.orange.wwwapi.config;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.orange.core.security.filter.WxAuthenticationFilter;
import com.orange.core.service.user.UserService;
import com.orange.wwwapi.security.handler.UserAuthenticationSuccessHandler;
import com.orange.wwwapi.security.handler.WxAccountAuthenticationFailHandler;
import com.orange.wwwapi.security.provider.WxAuthenticationProvider;
import com.orange.wwwapi.service.token.AccessTokenService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class WxAuthenticationSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

    private final AccessTokenService accessTokenService;
    private final UserDetailsService userDetailsService;
    private final UserService userService;
    private final WxMaService wxMaService;
    private final ObjectMapper objectMapper;

    public WxAuthenticationSecurityConfig(AccessTokenService accessTokenService, @Qualifier("wxUserDetailService") UserDetailsService userDetailsService,
                                          UserService userService, WxMaService wxMaService, ObjectMapper objectMapper) {
        this.accessTokenService = accessTokenService;
        this.userDetailsService = userDetailsService;
        this.userService = userService;
        this.wxMaService = wxMaService;
        this.objectMapper = objectMapper;
    }

    @Override
    public void configure(HttpSecurity http) {
        UserAuthenticationSuccessHandler successHandler = new UserAuthenticationSuccessHandler(accessTokenService, objectMapper);
        AuthenticationFailureHandler failHandler = new WxAccountAuthenticationFailHandler(objectMapper);

        AbstractAuthenticationProcessingFilter authenticationFilter = new WxAuthenticationFilter(objectMapper, successHandler, failHandler);
        ProviderManager providerManager = (ProviderManager) http.getSharedObject(AuthenticationManager.class);
        providerManager.setEraseCredentialsAfterAuthentication(false);
        authenticationFilter.setAuthenticationManager(providerManager);

        AuthenticationProvider authenticationProvider = new WxAuthenticationProvider(wxMaService, userDetailsService, userService);

        http.addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class).authenticationProvider(authenticationProvider);
    }
}
